<script lang="ts" setup>
import { apiRole } from "@/api/sys";
import { useMessage } from "@/hooks/web/use-message";
import { AdvancedFilter, Comparator, type AdvancedSearch, type PageInfo, type RoleInfo } from "@/models";
import { generateAuditColumns } from "@/utils";
import { computed, onMounted, reactive, ref } from "vue";
import { type VxeGridInstance, type VxeGridProps } from "vxe-table";
import Delete from "~icons/ep/delete";
import Edit from "~icons/ep/edit";
import Plus from "~icons/ep/plus";
import Search from "~icons/ep/search";
import EditRole from "./edit-role.vue";

//#region [state]
const keyword = ref<string>();
const hasChecked = computed(() => !!gridRef.value?.getCheckboxRecords().length);
const { confirmDelete } = useMessage();
const { LIKE } = Comparator;
//#endregion

//#region [grid]
const gridRef = ref<VxeGridInstance>();
const gridPager = ref<PageInfo>({ currentPage: 1, pageSize: 20, total: 0 });
const gridProps = reactive<VxeGridProps<RoleInfo>>({
  autoResize: true,
  size: "small",
  border: "full",
  showOverflow: "tooltip",
  columnConfig: { resizable: true, minWidth: 60 },
  rowConfig: { keyField: "id" },
  toolbarConfig: { slots: { buttons: "toolbar_buttons" } },
  pagerConfig: gridPager.value,
  columns: [
    { type: "checkbox", width: 60, align: "center" },
    { field: "code", title: "编码", width: 200 },
    { field: "name", title: "名称", width: 200 },
    { field: "description", title: "描述" },
    ...generateAuditColumns<RoleInfo>({ dateMode: "date" }),
    { title: "操作", width: 120, align: "center", fixed: "right", slots: { default: "field_ops" } },
  ],
});
//#endregion

//#region [form]
const editRef = ref<InstanceType<typeof EditRole>>();
//#endregion

//#region [action]
async function load() {
  gridProps.loading = true;
  const search: AdvancedSearch<RoleInfo> = { s: [{ f: "code", s: "ASC" }] };
  if (keyword.value) search.f = new AdvancedFilter<RoleInfo>({ code: { value: keyword.value }, name: { value: keyword.value, comparator: LIKE } }, "OR");
  const response = await apiRole.page<RoleInfo>(search, gridPager.value);
  gridRef.value?.clearCheckboxRow();
  if (response.value) {
    gridProps.data = response.value.data || [];
    gridPager.value = response.value.pageInfo;
  }
  gridProps.loading = false;
}
function handleAdd() {
  editRef.value?.open();
}
function handleEdit(role: RoleInfo) {
  editRef.value?.open(role);
}
function handleDel(role: RoleInfo) {
  confirmDelete(
    `是否删除角色【${role.name}(${role.code})】及其相关配置项？`,
    async () => {
      await apiRole.remove(role.id);
      await load();
    },
    { title: "删除角色确认" },
  );
}
function handleBatchDel() {
  const roles = gridRef.value?.getCheckboxRecords();
  if (roles && roles.length > 0) {
    confirmDelete(
      `是否删除勾选角色（共${roles.length}条）及其相关配置项？`,
      async () => {
        await apiRole.removeAll(roles.map((r) => r.id));
        await load();
      },
      { title: "删除角色确认" },
    );
  }
}
//#endregion

onMounted(() => {
  load();
});
</script>

<template>
  <div class="m-3">
    <el-form :inline="true">
      <el-form-item class="w-md">
        <el-input v-model="keyword" placeholder="请输入名称或编码" clearable @keyup.enter="load" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" :icon="Search" plain @click="load">搜索</el-button>
      </el-form-item>
    </el-form>

    <vxe-grid ref="gridRef" :="gridProps">
      <template #toolbar_buttons>
        <el-button type="primary" :icon="Plus" plain title="添加角色" @click="handleAdd">新增</el-button>
        <el-button type="danger" :icon="Delete" plain title="批量删除角色" :disabled="!hasChecked" @click="handleBatchDel">删除</el-button>
      </template>
      <template #field_ops="{ row }">
        <el-button size="small" type="warning" :icon="Edit" title="编辑" @click="handleEdit(row)"></el-button>
        <el-button size="small" type="danger" :icon="Delete" title="删除" @click="handleDel(row)"></el-button>
      </template>
    </vxe-grid>
  </div>

  <edit-role ref="editRef" @onsaved="load" />
</template>

<style lang="scss" scoped>
.el-button--small {
  padding: 5px;
}
</style>
